package org.linlinjava.litemall.admin.controller;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.validation.constraints.NotNull;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.linlinjava.litemall.admin.beans.Constants;
import org.linlinjava.litemall.admin.beans.annotation.LogAnno;
import org.linlinjava.litemall.admin.beans.annotation.LoginAdminShopId;
import org.linlinjava.litemall.admin.beans.dto.AdminDto;
import org.linlinjava.litemall.admin.beans.pojo.convert.BeanConvert;
import org.linlinjava.litemall.admin.beans.vo.AdminVo;
import org.linlinjava.litemall.admin.service.AdminService;
import org.linlinjava.litemall.admin.service.LogHelper;
import org.linlinjava.litemall.core.util.RegexUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.util.bcrypt.BCryptPasswordEncoder;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.domain.LitemallAdmin;
import org.linlinjava.litemall.db.domain.LitemallRole;
import org.linlinjava.litemall.db.domain.LitemallShop;
import org.linlinjava.litemall.db.domain.LitemallUser;
import org.linlinjava.litemall.db.service.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import static org.linlinjava.litemall.admin.util.AdminResponseCode.*;

/**
 * 管理员管理控制器
 *
 * @author yliyun
 * @date 2022/09/14
 */
@RestController
@RequestMapping("/admin/admin")
@Validated
public class AdminAdminController {

    /**
     * litemall管理服务
     */
    @Autowired
    private LitemallAdminService litemallAdminService;
    /**
     * 日志助手
     */
    @Autowired
    private LogHelper logHelper;
    /**
     * 管理服务
     */
    @Autowired
    private AdminService adminService;
    /**
     * litemall店服务
     */
    @Autowired
    private LitemallShopService litemallShopService;
    /**
     * litemall用户服务
     */
    @Autowired
    private LitemallUserService litemallUserService;
    /**
     * litemall地区服务
     */
    @Autowired
    private LitemallRegionService litemallRegionService;

    @Autowired
    private LitemallRoleService litemallRoleService;

    @ApiOperation("简单管理员列表")
    @GetMapping("/simple-list")
    @LogAnno
    public Object simpleList(@RequestParam(required = false) Integer shopId) {
        return ResponseUtil.ok(litemallAdminService.selectList(shopId));
    }
    /**
     * 列表
     *
     * @param nickname 昵称
     * @param shopId   商店id
     * @param roleId   角色id
     * @param page     页面
     * @param limit    限制
     * @param sort     排序
     * @param order    订单
     * @return {@link Object}
     */
    @GetMapping("/list")
    @LogAnno
    public Object list(String nickname,
                       @LoginAdminShopId Integer shopId,
                       Integer roleId,
                       @RequestParam(defaultValue = "1") Integer page,
                       @RequestParam(defaultValue = "10") Integer limit,
                       @Sort @RequestParam(defaultValue = "add_time") String sort,
                       @Order @RequestParam(defaultValue = "desc") String order) {
        IPage<LitemallAdmin> adminList = litemallAdminService.querySelective(nickname, shopId, roleId, page, limit, sort, order);
        /*List<LitemallAdmin> adminFilterList=adminList.getRecords().stream().filter(litemallAdmin -> {
            //查看角色
            List<LitemallRole> litemallRoles = litemallRoleService.queryRoleByIds(litemallAdmin.getRoleIds());
            for (LitemallRole litemallRole : litemallRoles) {
                return litemallRole.getType();
            }
            return false;
        }).collect(Collectors.toList());*/
        List<AdminVo> result = new ArrayList<>();
        for (LitemallAdmin litemallAdmin : adminList.getRecords()) {
        	AdminVo adminVo = new AdminVo();
        	BeanUtils.copyProperties(litemallAdmin, adminVo);
        	if(null != litemallAdmin.getLocationCountry()) {
        		adminVo.setCountry(litemallRegionService.findById(litemallAdmin.getLocationCountry()));
        	}
        	if(null != litemallAdmin.getLocationProvince()) {
        		adminVo.setProvince(litemallRegionService.findById(litemallAdmin.getLocationProvince()));
        	}
        	if(null != litemallAdmin.getLocationCity()) {
        		adminVo.setCity(litemallRegionService.findById(litemallAdmin.getLocationCity()));
        	}
            result.add(adminVo);
		}
        return ResponseUtil.okPage(adminList,result);
    }


    /**
     * 列表
     *
     * @param nickname 昵称
     * @param shopId   商店id
     * @param roleId   角色id
     * @param page     页面
     * @param limit    限制
     * @param sort     排序
     * @param order    订单
     * @return {@link Object}
     */
    @GetMapping("/listv2")
    @LogAnno
    public Object listv2(String nickname,
                       @LoginAdminShopId Integer shopId,
                       Integer roleId,
                       @RequestParam(defaultValue = "1") Integer page,
                       @RequestParam(defaultValue = "10") Integer limit,
                       @Sort @RequestParam(defaultValue = "add_time") String sort,
                       @Order @RequestParam(defaultValue = "desc") String order) {
        IPage<LitemallAdmin> adminList = litemallAdminService.querySelective(nickname, shopId, roleId, page, limit, sort, order);
        /*List<LitemallAdmin> adminFilterList=adminList.getRecords().stream().filter(litemallAdmin -> {
            //查看角色
            List<LitemallRole> litemallRoles = litemallRoleService.queryRoleByIds(litemallAdmin.getRoleIds());
            for (LitemallRole litemallRole : litemallRoles) {
                return !litemallRole.getType();
            }
            return false;
        }).collect(Collectors.toList());*/
        List<AdminVo> result = new ArrayList<>();
        for (LitemallAdmin litemallAdmin : adminList.getRecords()) {
            AdminVo adminVo = new AdminVo();
            BeanUtils.copyProperties(litemallAdmin, adminVo);
            if(null != litemallAdmin.getLocationCountry()) {
                adminVo.setCountry(litemallRegionService.findById(litemallAdmin.getLocationCountry()));
            }
            if(null != litemallAdmin.getLocationProvince()) {
                adminVo.setProvince(litemallRegionService.findById(litemallAdmin.getLocationProvince()));
            }
            if(null != litemallAdmin.getLocationCity()) {
                adminVo.setCity(litemallRegionService.findById(litemallAdmin.getLocationCity()));
            }
            result.add(adminVo);
        }
        return ResponseUtil.okPage(adminList,result );
    }




    /**
     * 验证
     *
     * @param admin 管理
     * @return {@link Object}
     */
    private Object validate(LitemallAdmin admin) {
        String name = admin.getUsername();
        if (StringUtils.isEmpty(name)) {
            return ResponseUtil.badArgument();
        }
        //if (!RegexUtil.isUsername(name)) {
        if (name.length()>100) {
            return ResponseUtil.fail(ADMIN_INVALID_NAME, "管理员名称不符合规定");
        }
        String password = admin.getPassword();
        if (StringUtils.isEmpty(password) || password.length() < 6) {
            return ResponseUtil.fail(ADMIN_INVALID_PASSWORD, "管理员密码长度不能小于6");
        }
        return null;
    }

    /**
     * 验证密码
     *
     * @param admin 管理
     * @return {@link Object}
     */
    private Object validatePassword(LitemallAdmin admin) {
        String password = admin.getPassword();
        if (!StringUtils.isEmpty(password) && password.length() < 6) {
            return ResponseUtil.fail(ADMIN_INVALID_PASSWORD, "管理员密码长度不能小于6");
        }
        return null;
    }


    /**
     * 创建
     *
     * @param dto dto
     * @return {@link Object}
     */
    @PostMapping("/create")
    @LogAnno
    public Object create(@RequestBody AdminDto dto) {
        LitemallAdmin admin = new LitemallAdmin();
        BeanUtils.copyProperties(dto, admin);
        Object error = validate(admin);
        if (error != null) {
            return error;
        }

        String username = admin.getUsername();
        List<LitemallAdmin> adminList = litemallAdminService.findAdmin(username);
        if (adminList.size() > 0) {
            return ResponseUtil.fail(ADMIN_NAME_EXIST, "管理员已经存在");
        }

        //校验邮箱
        if (!RegexUtil.isMobileValid(admin.getMobile()) && !RegexUtil.isEmailExact(admin.getEmail())) {
            return ResponseUtil.fail(AUTH_INVALID_MOBILE, "手机号或邮箱格式不正确");
        }

        //截取手机号
        if(admin.getMobile().startsWith(MOBILE_CODE_ONE)){
            admin.setMobile(admin.getMobile().substring(1,admin.getMobile().length()));
        }

        //判断添加的店员的角色，该店是否已存在店长和经理
        if(admin.getShopId() != null){
            List<LitemallAdmin> byShopId = litemallAdminService.findByShopId(admin.getShopId());
            if(Arrays.asList(admin.getRoleIds()).contains(Constants.SHOPKEEPER_ROLE_ID)){
                boolean hasShopkepper = byShopId.stream().anyMatch(ad -> {
                    return  Arrays.asList(ad.getRoleIds()).contains(Constants.SHOPKEEPER_ROLE_ID);
                });
                if(hasShopkepper){
                    return ResponseUtil.fail(SHOP_HAS_SHOPKEEPER, "该门店已存在店长");
                }
            }

            if(Arrays.asList(admin.getRoleIds()).contains(Constants.SHOP_MANAGER_ROLE_ID)){
                boolean hasManager = byShopId.stream().anyMatch(ad -> {
                    return  Arrays.asList(ad.getRoleIds()).contains(Constants.SHOP_MANAGER_ROLE_ID);
                });
                if(hasManager){
                    return ResponseUtil.fail(SHOP_HAS_MANAGER, "该门店已存在经理");
                }
            }
        }

        String rawPassword = admin.getPassword();
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        String encodedPassword = encoder.encode(rawPassword);
        admin.setPassword(encodedPassword);
        litemallAdminService.add(admin);
        logHelper.logAuthSucceed("添加管理员", username);


        //给管理员生成一个user，用于pos下单
        LitemallUser user = BeanConvert.toUser(admin);
        user.setInnerAccount(true);
        litemallUserService.add(user);
        return ResponseUtil.ok(admin);
    }

    /**
     * 读
     *
     * @param id id
     * @return {@link Object}
     */
    @GetMapping("/read")
    @LogAnno
    public Object read(@NotNull @RequestParam(value = "id") Integer id) {
        LitemallAdmin admin = litemallAdminService.findById(id);
        return ResponseUtil.ok(admin);
    }

    /**
     * 更新
     *
     * @param dto dto
     * @return {@link Object}
     */
    @PostMapping("/update")
    @LogAnno
    public Object update(@RequestBody AdminDto dto) {
        LitemallAdmin admin = new LitemallAdmin();
        BeanUtils.copyProperties(dto, admin);
        Object error = validatePassword(admin);
        if (error != null) {
            return error;
        }

        Integer anotherAdminId = admin.getId();
        if (anotherAdminId == null) {
            return ResponseUtil.badArgument();
        }
        //判断修改的账号是否重复
        if(litemallAdminService.findAdmin(admin.getUsername()).size()>0&&!(litemallAdminService.findById(dto.getId()).getUsername().equals(dto.getUsername()))){
            return ResponseUtil.fail("账号已存在");
        }

        if(!StringUtils.isEmpty(admin.getPassword())){
            String rawPassword = admin.getPassword();
            BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
            String encodedPassword = encoder.encode(rawPassword);
            admin.setPassword(encodedPassword);
        }

        if (!RegexUtil.isMobileValid(admin.getMobile()) && !RegexUtil.isEmailExact(admin.getEmail())) {
            return ResponseUtil.fail(AUTH_INVALID_MOBILE, "手机号或邮箱格式不正确");
        }

        if(admin.getShopId() != null){
            List<LitemallAdmin> byShopId = litemallAdminService.findByShopId(admin.getShopId());
            if(Arrays.asList(admin.getRoleIds()).contains(Constants.SHOPKEEPER_ROLE_ID)){
                boolean hasShopkepper = byShopId.stream().anyMatch(ad -> {
                    return !ad.getId().equals(admin.getId())   && Arrays.asList(ad.getRoleIds()).contains(Constants.SHOPKEEPER_ROLE_ID);
                });
                if(hasShopkepper){
                    return ResponseUtil.fail(SHOP_HAS_SHOPKEEPER, "该门店已存在店长");
                }
            }
            if(Arrays.asList(admin.getRoleIds()).contains(Constants.SHOP_MANAGER_ROLE_ID)){
                boolean hasManager = byShopId.stream().anyMatch(ad -> {
                    return !ad.getId().equals(admin.getId()) && Arrays.asList(ad.getRoleIds()).contains(Constants.SHOP_MANAGER_ROLE_ID);
                });
                if(hasManager){
                    return ResponseUtil.fail(SHOP_HAS_MANAGER, "该门店已存在经理");
                }
            }
        }


        if (litemallAdminService.updateById(admin) == 0) {
            return ResponseUtil.updatedDataFailed();
        }

        logHelper.logAuthSucceed("编辑管理员", admin.getUsername());

        //修改admin信息时，同时修改user信息
        LitemallAdmin info = litemallAdminService.findAdmin(admin.getId());
        LitemallUser litemallUser = litemallUserService.findByAdmin(info.getUsername(), true);
        if(litemallUser != null){
            LitemallUser user = BeanConvert.toUser(admin);
            user.setId(litemallUser.getId());
            litemallUserService.updateById2(user);
        }
        return ResponseUtil.ok(admin);
    }

    /**
     * 删除
     *
     * @param admin 管理
     * @return {@link Object}
     */
    @PostMapping("/delete")
    @LogAnno
    public Object delete(@RequestBody LitemallAdmin admin) {
        Integer anotherAdminId = admin.getId();
        if (anotherAdminId == null) {
            return ResponseUtil.badArgument();
        }

        // 管理员不能删除自身账号
        Subject currentUser = SecurityUtils.getSubject();
        LitemallAdmin currentAdmin = (LitemallAdmin) currentUser.getPrincipal();
        if (currentAdmin.getId().equals(anotherAdminId)) {
            return ResponseUtil.fail(ADMIN_DELETE_NOT_ALLOWED, "管理员不能删除自己账号");
        }

        Integer[] roleIds = currentAdmin.getRoleIds();
        if(!ObjectUtils.isEmpty(roleIds)){
            for (Integer roleId:roleIds) {
                if(roleId.equals(Constants.SHOPKEEPER_ROLE_ID)){
                    return ResponseUtil.fail(ADMIN_DELETE_NOT_ALLOWED, "已被选做店长的管理员不能被删除");
                }
            }
        }


        litemallAdminService.deleteById(anotherAdminId);
        //逻辑删除pos收银账号
        litemallUserService.deleteByUserName(currentAdmin.getUsername());
        logHelper.logAuthSucceed("删除管理员", admin.getUsername());
        return ResponseUtil.ok();
    }

    /**
     * 让店主
     *
     * @param shopId 商店id
     * @return {@link Object}
     */
    @GetMapping("/shop/shopkeeper")
    @LogAnno
    public Object getShopkeeper(@NotNull @LoginAdminShopId Integer shopId) {
        return adminService.findShopMemberByRole(shopId, Constants.SHOPKEEPER_ROLE_ID);
    }

    /**
     * 让商店经理
     *
     * @param shopId 商店id
     * @return {@link Object}
     */
    @GetMapping("/shop/manager")
    @LogAnno
    public Object getShopManager(@NotNull @LoginAdminShopId Integer shopId) {
        return adminService.findShopMemberByRole(shopId, Constants.SHOP_MANAGER_ROLE_ID);
    }

    /**
     * 得到车间成员
     *
     * @param shopId 商店id
     * @return {@link Object}
     */
    @GetMapping("/shop/members")
    @LogAnno
    public Object getShopMembers(@LoginAdminShopId Integer shopId) {
        if(shopId != null){
            return adminService.findShopMembers(shopId);
        }else{
            return adminService.all();
        }
    }

    /**
     * 所有
     *
     * @return {@link Object}
     */
    @GetMapping("/all")
    @LogAnno
    public Object all() {
        return adminService.all();
    }


    /**
     * 登录历史
     *
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation("首页近期登录记录")
    @GetMapping("/loginHistory")
    public ResponseUtil.Response loginHistory(){
        return adminService.loginHistory();
    }


    /**
     * 信息
     *
     * @return {@link Object}
     */
    @GetMapping("/info")
    @LogAnno
    public Object info() {
        LitemallAdmin admin = (LitemallAdmin)SecurityUtils.getSubject().getPrincipal();
        LitemallShop shop = litemallShopService.findById(admin.getShopId());
        Map<String, Object> map = new HashMap<>();
        map.put("admin", admin);
        map.put("shop", shop);
        return ResponseUtil.ok(map);
    }
}
